package jmine.tec.rpc.checkup;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;

import jmine.tec.rpc.common.serialization.Serializer;
import jmine.tec.rpc.common.serialization.SerializerBuilder;

/**
 * @author lundberg
 * @param <T> tipo da throwable
 */
public class ThrowableSerializationCheckup<T extends Throwable> {

    private final T throwable;

    private Serializer serializer;

    /**
     * @param throwable throwable
     */
    public ThrowableSerializationCheckup(T throwable) {
        this(throwable, SerializerBuilder.aSerializer().build());
    }

    /**
     * @param throwable throwable
     * @param serializer serializer
     */
    public ThrowableSerializationCheckup(T throwable, Serializer serializer) {
        this.throwable = throwable;
        this.serializer = serializer;
    }

    /**
     * Verifica se a representação pode ser serializada e deserializada.
     */
    public void check() {
        this.testSerializationFor(this.throwable);
    }

    /**
     * Tests serialization of a given object
     * 
     * @param original original object
     */
    protected void testSerializationFor(T original) {
        T deserialized = this.serializeAndDeserialize(original);
        assertThat("Unmarshalled an original do not match.", deserialized.getClass(), is(equalTo(((Class) original.getClass()))));
        assertThat("Unmarshalled an original do not match.", deserialized.getMessage(), is(equalTo((original.getMessage()))));
    }

    /**
     * @param original original
     * @return result
     */
    @SuppressWarnings("unchecked")
    protected T serializeAndDeserialize(T original) {
        try {
            InputStream stream = this.serializer.serialize(original);
            return (T) this.serializer.deserialize(stream);
        } catch (IOException e) {
            fail(e.getMessage());
            throw new IllegalStateException();
        } catch (ParseException e) {
            fail(e.getMessage());
            throw new IllegalStateException();
        }
    }

}
